<script setup>
// import HelloWorld from './components/HelloWorld.vue'
// 一个单元格宽度190
import { ref, onMounted, defineAsyncComponent, shallowRef, computed, nextTick } from "vue";
// import Comp1  from "./components/comp1.vue";

//加载待选组件列表
import { compList } from "./data.json"


import { useStore } from 'vuex'
const buffer = ref(null);
const dragContainer = ref(null)
const baseWidth = 190;
const baseHeight = 131.6;
const DragLeft = ref(null)
const DragRight = ref(null)
const currentProp = ref({})
const layout = ref([]);
const layout2 = ref([]);

const gridlayout = ref(null)
const gridlayout2 = ref(null)
const itemref = ref(null)
const itemref2 = ref(null)

const myHtml = ref('')
const isShow = ref(false)
// 存放实际的dom元素
const target = ref({})
const colNum = 4
const tempRef = ref(null);

const isDrag = ref(true);


// 两个目标区域 指示当前拖动到那个目标区域中
const area = ref('')


// 添加编辑和保存的模式
const isEdit = ref(false)

const store = useStore()

onMounted(() => {
  document.addEventListener("dragover", function (e) {
    mouseXY.value.x = e.clientX;
    mouseXY.value.y = e.clientY;
  }, false);


  // 恢复数据
  layout.value = store.state.layout
})

let mouseXY = ref({
  x: null,
  y: null
})
let DragPos = ref({ "x": null, "y": null, "w": 1, "h": 1, "i": null })
const drag = (e) => {
  console.log('当前元素被拖动');
  // isDrag.value = false

  let parentRect = DragLeft.value.getBoundingClientRect();
  let mouseInGrid = false;
  let parentRect2 = DragRight.value.getBoundingClientRect();
  // console.log(parentRect, 'kkk')
  if (((mouseXY.value.x > parentRect.left) && (mouseXY.value.x < parentRect.right)) && ((mouseXY.value.y > parentRect.top) && (mouseXY.value.y < parentRect.bottom))) {
    area.value = 'left'
    mouseInGrid = true;

  }
  else if (((mouseXY.value.x > parentRect2.left) && (mouseXY.value.x < parentRect2.right)) && ((mouseXY.value.y > parentRect2.top) && (mouseXY.value.y < parentRect2.bottom))) {
    area.value = 'right'
    mouseInGrid = true;

  }
  else {
    return
  }

  // 如果当前的元素被拖动到目标区域中
  // 如果当前的元素不在layout当中 就将他push 进去
  // 左边添加
  if (mouseInGrid === true && (area.value === 'left') && (layout.value.findIndex(item => item.i === 'drop')) === -1) {
    // 计算w和h

    let h = currentProp.value.lins * baseHeight / 65.8;
    let w = currentProp.value.cols * baseWidth / 95;
    // (layout.value.length * 2) % (colNum)
    // layout.value.length + (colNum)
    layout.value.push({
      x: (layout.value.length * 2) % (colNum),
      y: layout.value.length, // puts it at the bottom
      w,
      h,
      i: 'drop',
      id: currentProp.value.id
    });

  }
  if (mouseInGrid === true && (area.value === 'right') && (layout2.value.findIndex(item => item.i === 'drop2')) === -1) {
    // 计算w和h

    let h = currentProp.value.lins * baseHeight / 65.8;
    let w = currentProp.value.cols * baseWidth / 95;
    // (layout.value.length * 2) % (colNum)
    // layout.value.length + (colNum)
    layout2.value.push({
      x: (layout.value.length * 2) % (colNum),
      y: layout.value.length, // puts it at the bottom
      w,
      h,
      i: 'drop2',
      id: currentProp.value.id,
    });

  }
  console.log(layout.value, 'l1')
  console.log(layout2.value, 'l2')

  let index;
  if (area.value === 'left') {
    index = layout.value.findIndex(item => item.i === 'drop');
  } else if (area.value === 'right') {
    index = layout2.value.findIndex(item => item.i === 'drop2');

  }
  if (index !== -1) {
    // if (area.value === 'left') {
    //   try {
    //     gridlayout.value.$refs.item.children[layout.value.length].style.display = 'none'
    //   } catch { }

    // }

    // 拖进去之后这个值就不等于-1
    // dragContainer.value.dragging =  {"top": mouseXY.value.y - parentRect.top, "left": mouseXY.value.x - parentRect.left};
    // console.log(  dragContainer.value.calcXY)
    // console.log(gridlayout.value.$refs.item.children[0])
    // const el = gridlayout.value.$refs.item.children[index];
    // el.dragging =  {"top": mouseXY.value.y - parentRect.top, "left": mouseXY.value.x - parentRect.left};
    // let new_pos = el.calcXY(top,left) = el.calcXY(mouseXY.value.y - parentRect.top, mouseXY.value.x - parentRect.left);


    // 区分左右
    if (area.value === 'left') {

      // console.log()
      const el = itemref.value[index];
      if (!el) {
        return
      }
      el.dragging = {
        top: mouseXY.value.y - parentRect.top,
        left: mouseXY.value.x - parentRect.left
      }
      const new_pos = el.calcXY(mouseXY.value.y - parentRect.top, mouseXY.value.x - parentRect.left)
      console.log(new_pos, 'kkp')

      // const relx =parseInt((mouseXY.value.x - parentRect.left) / 95);
      // const rely =parseInt((mouseXY.value.y - parentRect.top) / 65.8)
      let h = currentProp.value.lins * baseHeight / 65.8;
      let w = currentProp.value.cols * baseWidth / 95;
      if (mouseInGrid === true) {
        // gridlayout.value.dragEvent('dragstart', currentProp.value.id,3, 4, 1, 1)
        // 手动算x

        gridlayout.value.dragEvent('dragstart', 'drop', new_pos.x, new_pos.y, h, w)
        DragPos.value.i = currentProp.value.id;
        DragPos.value.x = layout.value[index].x;
        DragPos.value.y = layout.value[index].y;
        DragPos.value.h = h;
        DragPos.value.w = w;

        console.log(DragPos, ';;;')
        // console.log(mouseXY.value.y - parentRect.top, mouseXY.value.x - parentRect.left,'实时位置')
      }
      if (mouseInGrid === false) {
        gridlayout.value.dragEvent('dragend', 'drop', new_pos.x, new_pos.y, h, w);
        layout.value = layout.value.filter(obj => obj.i !== 'drop');
        area.value = ''

      }
      console.log(layout.value)
    }
    if (area.value === 'right') {
      // console.log()
      const el = itemref2.value[index];
      if (!el) {
        return
      }
      el.dragging = {
        top: mouseXY.value.y - parentRect2.top,
        left: mouseXY.value.x - parentRect2.left
      }
      const new_pos = el.calcXY(mouseXY.value.y - parentRect2.top, mouseXY.value.x - parentRect2.left)
      console.log(new_pos, 'kky')

      // const relx =parseInt((mouseXY.value.x - parentRect2.left) / 95);
      // const rely = parseInt((mouseXY.value.y - parentRect2.top) / 65.8)
      let h = currentProp.value.lins * baseHeight / 65.8;
      let w = currentProp.value.cols * baseWidth / 95;
      if (mouseInGrid === true) {
        // gridlayout.value.dragEvent('dragstart', currentProp.value.id,3, 4, 1, 1)
        // 手动算x
        gridlayout2.value.dragEvent('dragstart', 'drop2', new_pos.x, new_pos.y, h, w)
        DragPos.value.i = currentProp.value.id;
        DragPos.value.x = layout2.value[index].x;
        DragPos.value.y = layout2.value[index].y;
        DragPos.value.h = h;
        DragPos.value.w = w;

        // console.log(DragPos,';;;')
        // console.log(mouseXY.value.y - parentRect.top, mouseXY.value.x - parentRect.left,'实时位置')
      }
      if (mouseInGrid === false) {
        gridlayout2.value.dragEvent('dragend', 'drop2', new_pos.x, new_pos.y, h, w);
        layout2.value = layout2.value.filter(obj => obj.i !== 'drop2');
        area.value = ''
      }
    }

  }

}

const getRandomKey = () => {
  return Math.random().toString(16).substring(2, 8)
}
const addNew = (lins, cols) => {

  // 清空当前缓冲区的元素
  dragContainer.value.innerHTML = ''
  // 在缓冲区中生成一个待添加的元素
  target.value = document.createElement('div');
  target.value.style.height = lins * baseHeight + 'px';
  target.value.style.width = cols * baseWidth + 'px';
  target.value.style.backgroundColor = 'rgb(67,198,249)';
  target.value.innerHTML = `${lins} x ${cols}`
  target.value.className = 'new-box'
  dragContainer.value.appendChild(target.value);
  // 为新元素创建一个对象 包括size和id
  // console.log()
  const id = getRandomKey()
  currentProp.value = {
    id,
    lins,
    cols
  }
}

const dragend = () => {
  let parentRect = DragLeft.value.getBoundingClientRect();
  let parentRect2 = DragRight.value.getBoundingClientRect();

  let mouseInGrid = false;
  if (((mouseXY.value.x > parentRect.left) && (mouseXY.value.x < parentRect.right)) && ((mouseXY.value.y > parentRect.top) && (mouseXY.value.y < parentRect.bottom))) {
    mouseInGrid = true;
    area.value = 'left'


  }
  if (((mouseXY.value.x > parentRect2.left) && (mouseXY.value.x < parentRect2.right)) && ((mouseXY.value.y > parentRect2.top) && (mouseXY.value.y < parentRect2.bottom))) {
    mouseInGrid = true;
    area.value = 'right'

  }
  if (mouseInGrid === true) {
    // 分别判断左右
    if (area.value === 'left') {
      gridlayout.value.dragEvent('dragend', 'drop', DragPos.value.x, DragPos.value.x, DragPos.value.h, DragPos.value.w);
      layout.value = layout.value.filter(obj => obj.i !== 'drop');
      console.log('结束', DragPos.value)
      // 拿到id判断是否能添加
      // 拿到height 和top 

      // const place = document.querySelector('.vue-grid-placeholder').style
      // const pHeight = place.height
      // const pTop = place.transform.split(',')[1];
      // console.log(pHeight,pTop)


      gridlayout.value.dragEvent('dragend', DragPos.value.i, DragPos.value.x, DragPos.value.y, DragPos.value.h, DragPos.value.w);

      console.log(document.querySelector('.vue-grid-placeholder'), 'lll')
      const place = DragLeft.value.querySelector('.vue-grid-placeholder').style;
      const pHeight = place.height
      const pTop = place.transform.split(',')[1];
      console.log(pHeight, pTop)
      if (parseInt(pHeight) + parseInt(pTop) <= 390) {
        layout.value.push({
          x: DragPos.value.x,
          y: DragPos.value.y,
          w: DragPos.value.w,
          h: DragPos.value.h,
          i: DragPos.value.i,
          compValue: currentProp.value.path,
          info: 'new',
          loc: 'left'
        });
        // 找到目标元素
        nextTick(() => {
          const cur = document.getElementById(DragPos.value.i)
          console.log(cur)
          cur.style.transform = place.transform;
        })
      }



      // console.log(pHeight,pTop)
      // const cur = document.getElementById(DragPos.value.i).style
      // const y = cur.transform.split(',')[1]
      // const yHeight = cur.height;
      // console.log(yHeight)
      // console.log(parseInt(y), '111')
      // console.log(parseInt(yHeight) + parseInt(y), '111')

      // if (parseInt(yHeight) + parseInt(y) > 390) {
      //   layout.value = layout.value.filter(obj => obj.i !== DragPos.value.i);
      // }




      console.log(layout, '数据')
    }
    if (area.value === 'right') {
      gridlayout2.value.dragEvent('dragend', 'drop2', DragPos.value.x, DragPos.value.x, DragPos.value.h, DragPos.value.w);
      layout2.value = layout2.value.filter(obj => obj.i !== 'drop2');
      gridlayout2.value.dragEvent('dragend', DragPos.value.i, DragPos.value.x, DragPos.value.y, DragPos.value.h, DragPos.value.w);

      const place = DragRight.value.querySelector('.vue-grid-placeholder').style;
      const pHeight = place.height
      const pTop = place.transform.split(',')[1];
      console.log(pHeight, pTop)
      if (parseInt(pHeight) + parseInt(pTop) <= 390) {
        layout2.value.push({
          x: DragPos.value.x,
          y: DragPos.value.y,
          w: DragPos.value.w,
          h: DragPos.value.h,
          i: DragPos.value.i,
          compValue: currentProp.value.path,
          info: 'new',
          loc: 'right'
        });
        // 找到目标元素
        nextTick(() => {
          const cur = document.getElementById(DragPos.value.i)
          console.log(cur)
          cur.style.transform = place.transform;

        })
      }

      // layout2.value.push({
      //   x: DragPos.value.x,
      //   y: DragPos.value.y,
      //   w: DragPos.value.w,
      //   h: DragPos.value.h,
      //   i: DragPos.value.i,
      //   compValue: currentProp.value.path,
      //   info: 'new',
      //   loc: 'right'

      // });


    }

    //销毁页面上的元素
    compRef.value = {};
    compShow.value = false;
    area.value = ''

    // isDrag.value = true

    // console.log(layout.value)

    //  gridlayout.value.$refs.item.children[DragPos.value.i].appendChild( target.value) 
    // const tar = document.querySelector(`#item${DragPos.value.i}`);
    // console.log( tar)
    // tar.innerHTML = target.value;
    // isShow.value = true

  }
}


const compRef = shallowRef({});
const compShow = ref(false)
const addComp = (lins, cols, item) => {
  // console.log('新增组件',lins,cols,item)

  compShow.value = true
  compRef.value = defineAsyncComponent(() => import(item.path));
  const id = getRandomKey()
  currentProp.value = {
    id,
    lins,
    cols,
    path: item.path
  }
}
// 子组件移动事件
const movedEvent = (i, newX, newY) => {
  console.log(i, newX, newY, '当前快一栋楼')
}
const total = computed(() => {
  return layout.value.map((item) => {
    return {
      ...item,
      comp: defineAsyncComponent(() => import(item.compValue))
    }
  })
})
const total2 = computed(() => {
  return layout2.value.map((item) => {
    return {
      ...item,
      comp: defineAsyncComponent(() => import(item.compValue))
    }
  })
})
const removeItem = (val) => {

  layout.value = layout.value.filter(item => item.i !== val.i);

  // 将项目还原到容器中
  // compShow.value = true;
  // compRef.value = defineAsyncComponent(() => import(val.compValue));
}

const handleSave = ()=>{
  if(isEdit.value){
    // 保存当前页面内容
    isEdit.value = false
    // 保存layout
    store.commit('saveLayout',layout.value)
  }
  else{
    // 进入编辑模式
    isEdit.value = true

  }
}
</script>

<template>
  <div class="demo-wrap">
    <div class="demo-content">
      <div class="demo-title">
        <!-- <div class="demo-btn" @click="addComp(1, 1)">
          点击新增组件
        </div> -->
        <div  class="demo-btn posi" @click="handleSave">
          {{isEdit?'保存':'编辑'}}
        </div>
        <template v-if="isEdit">
          <div v-for="item in compList" class="demo-btn" :key="item.path" @click="addComp(item.lins, item.cols, item)">
          新增{{ item.lins }} * {{ item.cols }}组件
        </div>
        </template>
        

      </div>
      <div class="demo-main">
        <div class="demo-left" ref="DragLeft">
          <grid-layout ref="gridlayout" class="num" :auto-size="false" :layout.sync="total" :col-num="4" :row-num="6"
            :margin="[0, 0]" :colWidth="95" :maxRows="6" :rowHeight="65" :responsive="false" :preventCollision="true"
            :is-draggable="true" :is-resizable="false" :use-css-transforms="true" :verticalCompact="true">
            <grid-item ref="itemref" :key="item.i" :id="item.i" v-for="(item, index) in total" :x="item.x" :y="item.y"
              :w="item.w" :h="item.h" :i="item.i" @moved="movedEvent">
              <!-- <span class="text">{{ item.i }}</span> -->
              <!-- <div :id="`item${index}`" ref="tempRef"></div> -->
              <component :is="item.comp" v-if="item.info && item.loc === 'left'">
                <div>{{ item.i }}</div>
              </component>
              <span class="remove" @click="removeItem(item)" v-if="isEdit">x</span>
            </grid-item>
          </grid-layout>


        </div>
        <div class="demo-middle" ref="buffer">
          <div class="drag-container" @drag="drag" ref="dragContainer" draggable="true" @dragend="dragend">
            <component :is="compRef" v-if="compShow"></component>
            <!--" -->
          </div>
        </div>
        <div class="demo-right" ref="DragRight">
          <grid-layout ref="gridlayout2" class="num" :auto-size="false" :layout="total2" :col-num="4" :row-num="6"
            :margin="[0, 0]" :colWidth="95" :maxRows="6" :rowHeight="65" :responsive="false" :preventCollision="true"
            :is-draggable="true" :is-resizable="false" :use-css-transforms="true">
            <grid-item ref="itemref2" :key="item.i" :id="item.i" v-for="(item, index) in total2" :x="item.x" :y="item.y"
              :w="item.w" :h="item.h" :i="item.i">
              <!-- <span class="text">{{ item.i }}</span> -->
              <!-- <div :id="`item${index}`" ref="tempRef"></div> -->
              <component :is="item.comp" v-if="item.info && item.loc === 'right'"></component>

            </grid-item>
          </grid-layout>
        </div>

      </div>
    </div>
  </div>



</template>

<style>
.demo-wrap {
  height: 100%;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.num {
  overflow: hidden;
  height: 390px !important;
}

.demo-content {
  height: 450px;
  width: 1600px;
  background-color: rgb(224, 219, 238);

}

.demo-main {
  display: flex
}

.demo-title {
  text-align: right;
  width: 100%;
  height: 47px;
  background-color: rgb(244, 208, 212);
  position: relative;
}

.demo-left {
  padding: 10px 5px;
  box-sizing: border-box;
  width: 400px;
  height: 407px;
  background-color: rgba(255, 255, 255, 0.3);
  flex: 0 0 auto;
}

.demo-right {
  padding: 10px 5px;
  box-sizing: border-box;

  width: 400px;
  height: 407px;
  background-color: rgba(255, 255, 255, 0.3);
  flex: 0 0 auto;

}

.demo-middle {
  padding: 20px;
  box-sizing: border-box;
  flex: 1 1 auto;
}

.demo-btn {
  height: 30px;
  background-color: rgb(27, 160, 53);
  display: inline-block;
  color: #fff;
  padding: 0 10px;
  line-height: 30px;
  border-radius: 5px;
  font-size: 13px;
  margin: 0 5px;


}

.new-box {
  font-size: 1.2em;
  color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
}

.drag-container {
  display: inline-block;
}

.remove {
  position: absolute;
  right: 15px;
  top: 5px;
  cursor: pointer;
}
.posi{
  position: absolute;
  left: 10px;
  top: 5px;
}
</style>
